package com.capgemini.cn.authority.rest.resource;

import com.capgemini.cn.authority.rest.exception.AuthRestBusinessException;
import com.capgemini.cn.authority.rest.service.GroupMemberService;
import com.capgemini.cn.authority.rest.service.GroupService;
import com.capgemini.cn.authority.rest.service.RoleService;
import com.capgemini.cn.authority.rest.valueobject.DataResponse;
import com.capgemini.cn.authority.rest.valueobject.DataStatus;
import com.capgemini.cn.authority.rest.valueobject.data.GroupListVO;
import com.capgemini.cn.authority.rest.valueobject.data.GroupMemberVO;
import com.capgemini.cn.authority.rest.valueobject.data.GroupVO;
import com.capgemini.cn.authority.rest.valueobject.data.RoleVO;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created at 2017/9/18
 *
 * @author Andriy
 */
@RestController
@RequestMapping(path = BaseResource.RESOURCE_PREFIX + "group")
public class GroupResource extends BaseResource<GroupVO> {

    @Autowired
    private GroupService groupService;

    @Autowired
    private GroupMemberService groupMemberService;

    @Autowired
    private RoleService roleService;

    @ApiIgnore
    @ApiOperation(value = "查询单个用户组详情")
    @Override
    public DataResponse<GroupVO> findByOne(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(name = ID_PARAM) long id) {
        return this.groupService.findById(id).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "查询单个用户组详情，包含其子集分组信息")
    @GetMapping(path = "detail/{id}")
    public DataResponse<GroupListVO> findByOneDetail(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(name = ID_PARAM) long id) {
        return this.groupService.findDetail(id).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiIgnore
    @ApiOperation(value = "查询所有用户组信息")
    @Override
    public DataResponse<List<GroupVO>> findAll(@ApiParam(value = PAGE_PARAM_COMMENT, name = PAGE_PARAM, required = true) @RequestParam(value = PAGE_PARAM) int page,
                                               @ApiParam(value = SIZE_PARAM_COMMENT, name = SIZE_PARAM, required = true) @RequestParam(value = SIZE_PARAM) int size,
                                               @ApiParam(value = ORDER_PARAM_COMMENT, name = ORDER_PARAM, required = true) @RequestParam(value = ORDER_PARAM) String order,
                                               @ApiParam(value = DIRECTION_PARAM_COMMENT, name = DIRECTION_PARAM, required = true) @RequestParam(value = DIRECTION_PARAM) Sort.Direction direction) {
        return this.groupService.findAll(page, size, order, direction).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "查询所有用户组信息")
    @GetMapping(value = "all-groups")
    public DataResponse<List<GroupVO>> findAll(@ApiParam(value = "是否查询根级用户组，默认值为TRUE即表示查询，设置为FALSE则表示查询所有的用户组信息", name = "isSearchRoot") @RequestParam(value = "isSearchRoot", defaultValue = "true") boolean isSearchRoot,
                                               @ApiParam(value = PAGE_PARAM_COMMENT, name = PAGE_PARAM, required = true) @RequestParam(value = PAGE_PARAM) int page,
                                               @ApiParam(value = SIZE_PARAM_COMMENT, name = SIZE_PARAM, required = true) @RequestParam(value = SIZE_PARAM) int size,
                                               @ApiParam(value = ORDER_PARAM_COMMENT, name = ORDER_PARAM, required = true) @RequestParam(value = ORDER_PARAM) String order,
                                               @ApiParam(value = DIRECTION_PARAM_COMMENT, name = DIRECTION_PARAM, required = true) @RequestParam(value = DIRECTION_PARAM) Sort.Direction direction) {
        return this.groupService.findAll(isSearchRoot, page, size, order, direction).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "删除单个用户组")
    @Override
    public DataResponse<String> remove(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(name = ID_PARAM) long id) throws AuthRestBusinessException {
        if (!this.groupService.delete(id)) throw new AuthRestBusinessException("删除主键ID值为" + id + "的用户组实体对象时操作失败！");
        return new DataResponse(DataStatus.SUCCESS, "");
    }

    @ApiOperation(value = "新增用户组")
    @PostMapping(path = "add")
    public DataResponse<GroupVO> add(@ApiParam(value = "用户组名称", name = "name", required = true) @RequestParam(name = "name") String name,
                                     @ApiParam(value = "用户组父级主键ID值", name = "parentId") @RequestParam(name = "parentId", required = false) Long parentId) {
        return this.groupService.add(new GroupVO(name, parentId)).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "更新指定用户组")
    @PutMapping(path = "update/{id}")
    public DataResponse<GroupVO> update(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(name = "id") long id,
                                        @ApiParam(value = "需要更新的属性列表，key为字符串类型用以标识需要更新的属性名称，value为对象类型用以存放更新后的数据值，例如：{\"name\":\"value\"}", name = "properties", required = true) @RequestParam(name = "properties") List<String> properties) throws AuthRestBusinessException, IOException {
        Map<String, Object> propMaps = new HashMap<>();
        ObjectMapper objectMapper = new ObjectMapper();
        for (String propData : properties) propMaps.putAll(objectMapper.readValue(propData, Map.class));
        return this.groupService.update(id, propMaps).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "查询用户组下的成员列表数据")
    @GetMapping(path = "members/{groupId}")
    public DataResponse<List<GroupMemberVO>> findMembers(@ApiParam(value = "用户组主键ID值", name = "groupId", required = true) @PathVariable(name = "groupId") long groupId) throws AuthRestBusinessException {
        return this.groupMemberService.findMemberByGroup(groupId).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "批量绑定用户至指定用户组")
    @PostMapping(path = "bind")
    public DataResponse<List<GroupMemberVO>> bindMember(@ApiParam(value = "用户组主键ID值", name = "groupId", required = true) @RequestParam(name = "groupId") long groupId,
                                                        @ApiParam(value = "在业务系统中用户的唯一标识，通常为业务系统的登录账号名，组成JSON数组的形式传递", name = "username", required = true) @RequestParam(name = "username") String... username) throws AuthRestBusinessException {
        return this.groupMemberService.bind(groupId, username).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "从用户组批量解绑指定用户")
    @DeleteMapping(path = "release")
    public DataResponse<String> releaseMember(@ApiParam(value = "用户组成员主键ID值，组成JSON数组的形式传递", name = ID_PARAM, required = true) @RequestParam(name = "id") Long... id) throws AuthRestBusinessException {
        if (!this.groupMemberService.delete(Arrays.asList(id)))
            throw new AuthRestBusinessException("解除主键ID值为" + id + "的用户组关系时操作失败！");
        return new DataResponse(DataStatus.SUCCESS, "");
    }

    @ApiOperation(value = "查询当前用户组所拥有的角色信息列表")
    @GetMapping(value = "role/{id}")
    public DataResponse<List<RoleVO>> findAllRoles(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(name = ID_PARAM) long id) {
        return this.roleService.findGroupInclusiveRole(id).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "查询当前用户组未分配的角色信息列表")
    @GetMapping(value = "exclude-role/{id}")
    public DataResponse<List<RoleVO>> findExclusiveRoles(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(name = ID_PARAM) long id) {
        return this.roleService.findGroupExclusiveRole(id).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "为用户组批量分配指定角色，返回用户组最新的角色绑定信息数据")
    @PostMapping(value = "assign/{id}")
    public DataResponse<List<RoleVO>> assignRole(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(name = ID_PARAM) long id,
                                                 @ApiParam(value = "需要分配的角色数据主键ID值，组成JSON数组的形式传递", name = "roleIds", required = true) @RequestParam(name = "roleIds") Long... roleIds) {
        return this.roleService.assignRole(id, roleIds).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "为用户组批量解绑指定角色，返回用户组最新的角色绑定信息数据")
    @DeleteMapping(value = "release-role/{id}")
    public DataResponse<List<RoleVO>> releaseRole(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(name = ID_PARAM) long id,
                                                  @ApiParam(value = "需要解绑的角色数据主键ID值，组成JSON数组的形式传递", name = "roleIds", required = true) @RequestParam(name = "roleIds") Long... roleIds) {
        return this.roleService.releaseRole(id, roleIds).setDataStatus(DataStatus.SUCCESS);
    }
}
